package com.pfzy.liveeventbusdemo

import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.widget.Toast
import androidx.annotation.Nullable
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import com.jeremyliao.liveeventbus.LiveEventBus
import com.pfzy.liveeventbusdemo.activity.ObserverActiveLevelActivity
import com.pfzy.liveeventbusdemo.activity.PostDelayActivity
import com.pfzy.liveeventbusdemo.activity.StickyActivity
import com.pfzy.liveeventbusdemo.databinding.ActivityLiveDataBusDemoBinding
import com.pfzy.liveeventbusdemo.event.DemoEvent
import com.pfzy.liveeventbusdemo.service.IpcService
import java.util.Random
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

class LiveEventBusDemo : AppCompatActivity() {
    private var sendCount = 0
    private var receiveCount = 0
    private var randomKey: String? = null
    private var binding: ActivityLiveDataBusDemoBinding? = null
    private val observer: Observer<String> =
        Observer { s -> Toast.makeText(this@LiveEventBusDemo, s, Toast.LENGTH_SHORT).show() }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        startService(Intent(this, IpcService::class.java))
        binding = DataBindingUtil.setContentView(this, R.layout.activity_live_data_bus_demo)
        binding?.handler = this
        binding?.lifecycleOwner = this

        LiveEventBus
            .get(KEY_TEST_OBSERVE, String::class.java)
            .observe(this,
                { s -> Toast.makeText(this@LiveEventBusDemo, s, Toast.LENGTH_SHORT).show() })

        // 以Forever模式订阅消息
        LiveEventBus
            .get(KEY_TEST_OBSERVE_FOREVER, String::class.java)
            .observeForever(observer)

        // 以生命周期感知模式订阅消息
        LiveEventBus
            .get(KEY_TEST_CLOSE_ALL_PAGE, Boolean::class.java)
            .observe(this, object : Observer<Boolean> {
                override fun onChanged(@Nullable b: Boolean) {
                    if (b) {
                        finish()
                    }
                }
            })

        LiveEventBus
            .get(KEY_TEST_MULTI_THREAD_POST, String::class.java)
            .observe(this, { receiveCount++ })

        LiveEventBus
            .get(KEY_TEST_ACTIVE_LEVEL, String::class.java)
            .observe(this, object : Observer<String> {
                override fun onChanged(@Nullable s: String) {
                    Toast.makeText(
                        this@LiveEventBusDemo, "Receive message: $s",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            })

        LiveEventBus
            .get(KEY_TEST_ACTIVE_LEVEL_SINGLE, String::class.java)
            .observe(this, object : Observer<String> {
                override fun onChanged(@Nullable s: String) {
                    Toast.makeText(
                        this@LiveEventBusDemo, "Receive message: $s",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            })

        LiveEventBus
            .get(KEY_TEST_DELAY_LIFE, String::class.java)
            .observe(this, object : Observer<String> {
                override fun onChanged(@Nullable s: String) {
                    Toast.makeText(
                        this@LiveEventBusDemo, "Receive message: $s",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            })

        /**
         * 接收自定义消息
         */
        LiveEventBus.get(DemoEvent::class.java)
            .observe(this,object : Observer<DemoEvent>{
                override fun onChanged(@Nullable demoEvent: DemoEvent) {
                    Toast.makeText(
                        this@LiveEventBusDemo, "Receive message: " +
                                demoEvent.content, Toast.LENGTH_SHORT
                    ).show()
                }
            })

        testMessageSetBeforeOnCreate()
    }

    private fun testMessageSetBeforeOnCreate() {
        // 先发出一个消息
        LiveEventBus.get(
            KEY_TEST_MSG_SET_BEFORE_ON_CREATE,
            String::class.java
        ).post("msg set before")

        // 然后订阅这个消息
        LiveEventBus
            .get(KEY_TEST_MSG_SET_BEFORE_ON_CREATE, String::class.java)
            .observe(this,
                { s -> Toast.makeText(this@LiveEventBusDemo, s, Toast.LENGTH_SHORT).show() })
    }

    override fun onDestroy() {
        super.onDestroy()
        LiveEventBus
            .get(KEY_TEST_OBSERVE_FOREVER, String::class.java)
            .removeObserver(observer)
    }

    fun sendMsgByPostValue() {
        // 不定义消息直接发送
        LiveEventBus.get<Any>(KEY_TEST_OBSERVE)
            .post("Message By PostValue: " + Random().nextInt(100))
    }

    fun sendMsgToForeverObserver() {
        // 不定义消息直接发送
        LiveEventBus.get<Any>(KEY_TEST_OBSERVE_FOREVER)
            .post("Message To ForeverObserver: " + Random().nextInt(100))
    }

    fun sendMsgToStickyReceiver() {
        LiveEventBus.get<Any>(KEY_TEST_STICKY)
            .post("Message Sticky: " + Random().nextInt(100))
    }

    fun startStickyActivity() {
        startActivity(Intent(this, StickyActivity::class.java))
    }

    fun startNewActivity() {
        startActivity(Intent(this, LiveEventBusDemo::class.java))
    }

    fun closeAll() {
        LiveEventBus.get<Any>(KEY_TEST_CLOSE_ALL_PAGE).post(true)
    }

    fun postValueCountTest() {
        sendCount = 1000
        receiveCount = 0
        val threadPool = Executors.newFixedThreadPool(2)
        for (i in 0 until sendCount) {
            threadPool.execute {
                LiveEventBus.get<Any>(KEY_TEST_MULTI_THREAD_POST)
                    .post("test_data")
            }
        }
        Handler().postDelayed({
            Toast.makeText(
                this@LiveEventBusDemo, "sendCount: " + sendCount +
                        " | receiveCount: " + receiveCount, Toast.LENGTH_LONG
            ).show()
        }, 1000)
    }

    fun testMessageSetBefore() {
        //先动态生成一个key
        randomKey = "key_random_" + Random().nextInt()
        //然后发出一个消息
        LiveEventBus.get(randomKey!!, String::class.java).post("msg set before")
        //然后订阅这个消息
        LiveEventBus
            .get(randomKey!!, String::class.java)
            .observe(this,
                { s -> Toast.makeText(this@LiveEventBusDemo, s, Toast.LENGTH_SHORT).show() })
    }

    fun sendMessageSetBefore() {
        LiveEventBus.get(randomKey!!, String::class.java).post("msg set after")
    }

    fun testObserverActiveLevel() {
        startActivity(Intent(this, ObserverActiveLevelActivity::class.java))
    }

    /**
     * App之间发送消息
     */
    fun testBroadcast() {
        LiveEventBus
            .get<Any>(KEY_TEST_BROADCAST)
            .postAcrossApp("broadcast msg")
    }

    /**
     * App内发送消息，跨进程使用
     */
    fun testBroadcastInApp() {
        LiveEventBus
            .get<Any>(KEY_TEST_BROADCAST_IN_APP)
            .postAcrossProcess("broadcast msg")
    }

    fun testBroadcastGlobal() {
        LiveEventBus
            .get<Any>(KEY_TEST_BROADCAST_GLOBAL)
            .postAcrossApp("broadcast msg")
    }

    fun testDelayLife() {
        startActivity(Intent(this, PostDelayActivity::class.java))
    }

    /**
     * 发送自定义消息
     */
    fun sendDemoEvent() {
        /**
         * 先定义消息，再发送消息
         */
        LiveEventBus
            .get(DemoEvent::class.java)
            .post(DemoEvent("Hello world"))
    }

    companion object {
        const val KEY_TEST_OBSERVE = "key_test_observe"
        const val KEY_TEST_OBSERVE_FOREVER = "key_test_observe_forever"
        const val KEY_TEST_STICKY = "key_test_sticky"
        const val KEY_TEST_MULTI_THREAD_POST = "key_test_multi_thread_post"
        const val KEY_TEST_MSG_SET_BEFORE_ON_CREATE = "key_test_msg_set_before_on_create"
        const val KEY_TEST_CLOSE_ALL_PAGE = "key_test_close_all_page"
        const val KEY_TEST_ACTIVE_LEVEL = "key_test_active_level"
        const val KEY_TEST_ACTIVE_LEVEL_SINGLE = "key_test_active_level_single"
        const val KEY_TEST_BROADCAST = "key_test_broadcast"
        const val KEY_TEST_BROADCAST_IN_APP = "key_test_broadcast_in_app"
        const val KEY_TEST_BROADCAST_GLOBAL = "key_test_broadcast_global"
        const val KEY_TEST_DELAY_LIFE = "key_test_delay_life"
    }
}
